﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Win32;

namespace Com.CodePlex.SPC3.SPbAM.Service {

	/*
	//http://stackoverflow.com/questions/1043918/open-file-dialog-mvvm
	public interface IFileDialogService {
		//string FileName { get; }
		string OpenFileDialog();
	}
	 * */

	/*
	//http://stackoverflow.com/questions/3801681/good-or-bad-practise-for-dialogs-in-wpf-with-mvvm
	public class FileDialogService : IFileDialogService {
		public string OpenFileDialog() { 
			//var win = new WindowDialog(); 
			//win.Title = titel;
			//win.DataContext = datacontext;
			//return win.ShowDialog();
			return "";
		}
	}
	 * */

	//http://waf.codeplex.com/
	public interface IFileDialogService {
		FileDialogResult ShowOpenFileDialog(IEnumerable<FileType> fileTypes, FileType defaultFileType, string defaultFileName);

		FileDialogResult ShowSaveFileDialog(IEnumerable<FileType> fileTypes, FileType defaultFileType, string defaultFileName);
	}

	public class FileDialogService : IFileDialogService {
		/// <summary>
		/// Shows the open file dialog box that allows a user to specify a file that should be opened.
		/// </summary>
		/// <param name="fileTypes">The supported file types.</param>
		/// <param name="defaultFileType">Default file type.</param>
		/// <param name="defaultFileName">Default filename. The directory name is used as initial directory when it is specified.</param>
		/// <returns>A FileDialogResult object which contains the filename selected by the user.</returns>
		/// <exception cref="ArgumentNullException">fileTypes must not be null.</exception>
		/// <exception cref="ArgumentException">fileTypes must contain at least one item.</exception>
		public FileDialogResult ShowOpenFileDialog(IEnumerable<FileType> fileTypes, FileType defaultFileType, string defaultFileName) {
			if (fileTypes == null) { throw new ArgumentNullException("fileTypes"); }
			if (!fileTypes.Any()) { throw new ArgumentException("The fileTypes collection must contain at least one item."); }

			OpenFileDialog dialog = new OpenFileDialog();

			return ShowFileDialog(dialog, fileTypes, defaultFileType, defaultFileName);
		}

		/// <summary>
		/// Shows the save file dialog box that allows a user to specify a filename to save a file as.
		/// </summary>
		/// <param name="fileTypes">The supported file types.</param>
		/// <param name="defaultFileType">Default file type.</param>
		/// <param name="defaultFileName">Default filename. The directory name is used as initial directory when it is specified.</param>
		/// <returns>A FileDialogResult object which contains the filename entered by the user.</returns>
		/// <exception cref="ArgumentNullException">fileTypes must not be null.</exception>
		/// <exception cref="ArgumentException">fileTypes must contain at least one item.</exception>
		public FileDialogResult ShowSaveFileDialog(IEnumerable<FileType> fileTypes, FileType defaultFileType, string defaultFileName) {
			if (fileTypes == null) { throw new ArgumentNullException("fileTypes"); }
			if (!fileTypes.Any()) { throw new ArgumentException("The fileTypes collection must contain at least one item."); }

			SaveFileDialog dialog = new SaveFileDialog();

			return ShowFileDialog(dialog, fileTypes, defaultFileType, defaultFileName);
		}

		private static FileDialogResult ShowFileDialog(FileDialog dialog, IEnumerable<FileType> fileTypes, FileType defaultFileType, string defaultFileName) {
			int filterIndex = fileTypes.ToList().IndexOf(defaultFileType);
			if (filterIndex >= 0) { dialog.FilterIndex = filterIndex + 1; }
			if (!string.IsNullOrEmpty(defaultFileName)) {
				dialog.FileName = Path.GetFileName(defaultFileName);
				string directory = Path.GetDirectoryName(defaultFileName);
				if (!string.IsNullOrEmpty(directory)) {
					dialog.InitialDirectory = directory;
				}
			}

			dialog.Filter = CreateFilter(fileTypes);
			if (dialog.ShowDialog() == true) {
				if (dialog.FilterIndex - 1 < fileTypes.Count()) {
					defaultFileType = fileTypes.ElementAt(dialog.FilterIndex - 1);
				} else {
					defaultFileType = null;
				}
				return new FileDialogResult(dialog.FileName, defaultFileType);
			} else {
				return new FileDialogResult();
			}
		}

		private static string CreateFilter(IEnumerable<FileType> fileTypes) {
			string filter = "";
			foreach (FileType fileType in fileTypes) {
				if (!String.IsNullOrEmpty(filter)) { filter += "|"; }
				filter += fileType.Description + "|*" + fileType.FileExtension;
			}
			return filter;
		}
	}

	public class FileDialogResult {
		private readonly string fileName;
		private readonly FileType selectedFileType;


		/// <summary>
		/// Initializes a new instance of the <see cref="FileDialogResult"/> class with null values.
		/// Use this constructor when the user canceled the file dialog box.
		/// </summary>
		public FileDialogResult()
			: this(null, null) {
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="FileDialogResult"/> class.
		/// </summary>
		/// <param name="fileName">The filename entered by the user.</param>
		/// <param name="selectedFileType">The file type selected by the user.</param>
		public FileDialogResult(string fileName, FileType selectedFileType) {
			this.fileName = fileName;
			this.selectedFileType = selectedFileType;
		}


		/// <summary>
		/// Gets a value indicating whether this instance contains valid data. This property returns <c>false</c>
		/// when the user canceled the file dialog box.
		/// </summary>
		public bool IsValid { get { return FileName != null && SelectedFileType != null; } }

		/// <summary>
		/// Gets the filename entered by the user or <c>null</c> when the user canceled the dialog box.
		/// </summary>
		public string FileName { get { return fileName; } }

		/// <summary>
		/// Gets the file type selected by the user or <c>null</c> when the user canceled the dialog box.
		/// </summary>
		public FileType SelectedFileType { get { return selectedFileType; } }
	}

	public class FileType {
		private readonly string description;
		private readonly string fileExtension;


		/// <summary>
		/// Initializes a new instance of the <see cref="FileType"/> class.
		/// </summary>
		/// <param name="description">The description of the file type.</param>
		/// <param name="fileExtension">The file extension. This string has to start with a '.' point.</param>
		/// <exception cref="ArgumentException">description is null or an empty string.</exception>
		/// <exception cref="ArgumentException">fileExtension is null, an empty string or doesn't start with a '.' point character.</exception>
		public FileType(string description, string fileExtension) {
			if (string.IsNullOrEmpty(description)) { throw new ArgumentException("The argument description must not be null or empty."); }
			if (string.IsNullOrEmpty(fileExtension)) { throw new ArgumentException("The argument fileExtension must not be null or empty."); }
			if (fileExtension[0] != '.') { throw new ArgumentException("The argument fileExtension must start with the '.' character."); }

			this.description = description;
			this.fileExtension = fileExtension;
		}


		/// <summary>
		/// Gets the description of the file type.
		/// </summary>
		public string Description { get { return description; } }

		/// <summary>
		/// Gets the file extension. This string start with a '.' point.
		/// </summary>
		public string FileExtension { get { return fileExtension; } }
	}

	/*
<Window x:Class="WindowDialog"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"      Title="WindowDialog"      WindowStyle="SingleBorderWindow"      WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight">     <ContentPresenter x:Name="DialogPresenter" Content="{Binding .}">      </ContentPresenter> </Window> 
	 * */
}